package com.glodon.paas.message.adapter;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Don Li
 */
@XmlSeeAlso({MapAdapter.Adapter.class, MapAdapter.MapElement.class})
public class MapAdapter<K, V> extends XmlAdapter<MapAdapter.Adapter<K, V>, Map<K, V>> {
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "Adapter", namespace = "MapAdapter")
    public static final class Adapter<K, V> {

        List<MapElement<K, V>> items;

        public Adapter() {
        }

        public Adapter(Map<K, V> map) {
            items = new ArrayList<MapElement<K, V>>(map.size());
            for (Map.Entry<K, V> entry : map.entrySet()) {
                items.add(new MapElement<K, V>(entry));
            }
        }
    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "MapElement", namespace = "MapAdapter")
    public static final class MapElement<K, V> {
        private K key;
        private V value;

        public MapElement() {
        }

        public MapElement(K key, V value) {
            this.key = key;
            this.value = value;
        }

        public MapElement(Map.Entry<K, V> entry) {
            key = entry.getKey();
            value = entry.getValue();
        }

        public K getKey() {
            return key;
        }

        public void setKey(K key) {
            this.key = key;
        }

        public V getValue() {
            return value;
        }

        public void setValue(V value) {
            this.value = value;
        }
    }

    @Override
    public Adapter<K, V> marshal(Map<K, V> map) throws Exception {
        if (map == null) {
            return null;
        }
        return new Adapter<K, V>(map);
    }

    @Override
    public Map<K, V> unmarshal(Adapter<K, V> adapter) throws Exception {
        if (adapter == null) return null;

        Map<K, V> map = new HashMap<K, V>(adapter.items.size());
        for (MapElement<K, V> element : adapter.items) {
            map.put(element.getKey(), element.getValue());
        }
        return map;
    }
}
